//
//  ZFileOperationsPrivate.h
//  Part of Z-Way.C library
//
//  Created by Pavel Kulaha.
//  Based on Z-Way source code written by Christian Paetz and Poltorak Serguei
//
//  Copyright (c) 2024 Z-Wave.Me
//  All rights reserved
//  info@z-wave.me
//
//  This source file is subject to the terms and conditions of the
//  Z-Wave.Me Software License Agreement which restricts the manner
//  in which it may be used.
//

#ifndef zfile_operations_private_h
#define zfile_operations_private_h

#include "ZPlatform.h"
#include "ZLog.h"

typedef struct _ZFileOperationsTarDataOutput_s
{
    ZWCSTR file_data;
    size_t file_size;
    ZWBOOL compressed;
} _ZFileOperationsTarDataOutput_t;

typedef enum _ZFileOperationsTypeFile_s
{
    _ZFileOperationsTypeFileReg,
    _ZFileOperationsTypeFileDir,
    _ZFileOperationsTypeFileLink,
} _ZFileOperationsTypeFile_t;

typedef struct _ZFileOperationsLstat_s
{
    time_t mtime;
    _ZFileOperationsTypeFile_t type;
    dev_t st_rdev;
    size_t st_size;
    mode_t st_mode;
    uid_t st_uid;
    gid_t st_gid;
} _ZFileOperationsLstat_t;

#if !defined(_WINDOWS)
#define Z_FILE_PATH_SEPARATOR_STR "/"
#define Z_FILE_PATH_SEPARATOR_CHAR Z_FILE_PATH_SEPARATOR_STR[0]
#endif

#define ZFILE_OPEN_FLAGS_RDONLY O_RDONLY
#define ZFILE_OPEN_FLAGS_WRONLY O_WRONLY
#define ZFILE_OPEN_FLAGS_RDWR O_RDWR
#define ZFILE_OPEN_FLAGS_CREAT O_CREAT
#define ZFILE_OPEN_FLAGS_TRUNC O_TRUNC
#define ZFILE_OPEN_FLAGS_EXCL O_EXCL

#define ZFILE_OPEN_MODE_SET_UID S_ISUID
#define ZFILE_OPEN_MODE_SET_GID S_ISGID
#define ZFILE_OPEN_MODE_USER_R S_IRUSR
#define ZFILE_OPEN_MODE_USER_W S_IWUSR
#define ZFILE_OPEN_MODE_USER_X S_IXUSR
#define ZFILE_OPEN_MODE_USER_RWX S_IRWXU
#define ZFILE_OPEN_MODE_GROUP_R S_IRGRP
#define ZFILE_OPEN_MODE_GROUP_W S_IWGRP
#define ZFILE_OPEN_MODE_GROUP_X S_IXGRP
#define ZFILE_OPEN_MODE_GROUP_RWX S_IRWXG
#define ZFILE_OPEN_MODE_OTHER_R S_IROTH
#define ZFILE_OPEN_MODE_OTHER_W S_IWOTH
#define ZFILE_OPEN_MODE_OTHER_X S_IXOTH
#define ZFILE_OPEN_MODE_OTHER_RWX S_IRWXO

#define ZFILE_SEEK_SET SEEK_SET
#define ZFILE_SEEK_CUR SEEK_CUR
#define ZFILE_SEEK_END SEEK_END

ZWEXPORT_PRIVATE ZWError _zfile_clear_fn_add(const ZWLog log, size_t (*clear)(void *const ctx, const size_t n, const ZWBOOL force), void *const ctx);
ZWEXPORT_PRIVATE void _zfile_clear_fn_del(size_t (*const clear)(void *const ctx, const size_t n, const ZWBOOL force), void *const ctx);

ZWEXPORT_PRIVATE ZWError _zfile_seek(const ZWLog log, const ZW_FILE_HANDLE fd, const size_t position, const ZWDWORD mode);
ZWEXPORT_PRIVATE ZWError _zfile_read(const ZWLog log, const ZW_FILE_HANDLE fd, void *const ptr, const size_t n);
ZWEXPORT_PRIVATE ZWError _zfile_write(const ZWLog log, const ZW_FILE_HANDLE fd, const void *const ptr, const size_t n);
ZWEXPORT_PRIVATE ZWError _zfile_open(const ZWLog log, ZW_FILE_HANDLE *const p_fd, const ZWCSTR path, const ZWDWORD flags, const ZWDWORD mode);
ZWEXPORT_PRIVATE ZWError _zfile_open_tmp_ext(const ZWLog log, ZW_FILE_HANDLE *const p_fd, ZWSTR *const p_path, const ZWDWORD mode, ZWCSTR path);
static inline ZWError _zfile_open_tmp(const ZWLog log, ZW_FILE_HANDLE *const p_fd, ZWSTR *const p_path, const ZWDWORD mode)
{
    return _zfile_open_tmp_ext(log, p_fd, p_path, mode, NULL);
}
static inline void _zfile_close(const ZW_FILE_HANDLE fd)
{
    (void)close(fd);
}
ZWEXPORT_PRIVATE ZWError _zfile_lstat(const ZWLog log, const ZWCSTR path, _ZFileOperationsLstat_t *const res);
ZWEXPORT_PRIVATE ZWError _zfile_access(const ZWLog log, const ZWCSTR path, const int mode);
ZWEXPORT_PRIVATE ZWError _zfile_rename(const ZWLog log, const ZWCSTR src_path, const ZWCSTR dst_path);
ZWEXPORT_PRIVATE ZWError _zfile_remove(const ZWLog log, const ZWCSTR path);
ZWEXPORT_PRIVATE ZWError _zfile_mkdir(const ZWLog log, const ZWCSTR dir_path, const mode_t mode);
ZWEXPORT_PRIVATE ZWError _zfile_remove_recursive_ext(const ZWLog log, const ZWCSTR path, void *const arg, ZWBOOL (*const filter)(void *const arg, const ZWCSTR path, const size_t length, const _ZFileOperationsLstat_t *const st));
static inline ZWError _zfile_remove_recursive(const ZWLog log, const ZWCSTR path)
{
    return _zfile_remove_recursive_ext(log, path, NULL, NULL);
}
ZWEXPORT_PRIVATE ZWCSTR _zfile_get_mime_type(const ZWCSTR filename);
ZWEXPORT_PRIVATE ZWError _zfile_tar_data_find_file(const ZWLog logger, const void *const tarData, const size_t tarSize, const ZWCSTR fileName, _ZFileOperationsTarDataOutput_t *const output);
ZWEXPORT_PRIVATE ZWError _zfile_dir_recursive(const ZWLog log, const ZWCSTR path, void *const arg, ZWBOOL (*const dir_loop)(void *const arg, const ZWLog log, const ZWCSTR path, const size_t length));
ZWEXPORT_PRIVATE ZWError _zfile_copy_recursive_ext(const ZWLog log, const ZWCSTR src, const ZWCSTR dst, void *const arg, ZWBOOL (*const filter)(void *const arg, const ZWCSTR path, const size_t length));
static inline ZWError _zfile_copy_recursive(const ZWLog log, const ZWCSTR src, const ZWCSTR dst)
{
    return _zfile_copy_recursive_ext(log, src, dst, NULL, NULL);
}

ZWEXPORT_PRIVATE ZWCSTR _zfile_get_path_tmp_data(void);

#if defined(_WINDOWS)
ZWEXPORT_PRIVATE void flockfile(FILE *filehandle);
ZWEXPORT_PRIVATE void funlockfile(FILE *filehandle);
#endif

#endif//zfile_operations_private_h
